package com.hildeberto.versions;

import com.hildeberto.versions.model.CommitElement;
import com.hildeberto.versions.model.Config;
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Callback;

public class VersionsApp extends Application {

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) {
        primaryStage.setTitle("Versions");

        BorderPane root = new BorderPane();

        VBox messageArea = new VBox();
        messageArea.setPadding(new Insets(10, 10, 10, 10));
        messageArea.setSpacing(5);

        Label lblMessage = new Label("Message");
        messageArea.getChildren().add(lblMessage);

        final TextArea txaMessage = new TextArea();
        txaMessage.setPrefRowCount(3);
        messageArea.getChildren().add(txaMessage);

        HBox historyMessageArea = new HBox();
        historyMessageArea.setSpacing(5);
        Label lblHistoryMessage = new Label("Recent Messages:");
        historyMessageArea.getChildren().add(lblHistoryMessage);
        final ComboBox<String> cbxHistoryMessage = new ComboBox<String>();
        cbxHistoryMessage.getItems().addAll(Config.PROPERTIES.getHistoryMessageList());
        cbxHistoryMessage.setVisibleRowCount(5);
        cbxHistoryMessage.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent actionEvent) {
                txaMessage.setText(cbxHistoryMessage.getValue());
            }
        });
        historyMessageArea.getChildren().add(cbxHistoryMessage);
        messageArea.getChildren().add(historyMessageArea);

        root.setTop(messageArea);

        TabPane tbpCommitContent = new TabPane();
        tbpCommitContent.setTabClosingPolicy(TabPane.TabClosingPolicy.UNAVAILABLE);

        Tab tabList = new Tab("List");

        TableView tblCommitContentList = new TableView();
        tblCommitContentList.setEditable(true);

        TableColumn clnInclude = new TableColumn("In");
        clnInclude.setMaxWidth(30);
        clnInclude.setCellValueFactory(new PropertyValueFactory<CommitElement.Element, Boolean>("included"));
        Callback<TableColumn<CommitElement.Element, Boolean>, TableCell<CommitElement.Element, Boolean>> booleanCellFactory =
                new Callback<TableColumn<CommitElement.Element, Boolean>, TableCell<CommitElement.Element, Boolean>>() {
                    @Override
                    public TableCell<CommitElement.Element, Boolean> call(TableColumn<CommitElement.Element, Boolean> elementBooleanTableColumn) {
                        return new BooleanCell();
                    }
                };
        clnInclude.setCellFactory(booleanCellFactory);

        TableColumn clnStatus = new TableColumn("Status");
        clnStatus.setMinWidth(60);
        clnStatus.setCellValueFactory(new PropertyValueFactory<CommitElement.Element, String>("status"));
        TableColumn clnPath = new TableColumn("Path");
        clnPath.setMinWidth(200);
        clnPath.setCellValueFactory(new PropertyValueFactory<CommitElement.Element, String>("path"));
        TableColumn clnModified = new TableColumn("Modified");
        clnModified.setMinWidth(60);
        clnModified.setCellValueFactory(new PropertyValueFactory<CommitElement.Element, String>("date"));
        CommitElement commitElement = new CommitElement();
        ObservableList<CommitElement.Element> elements = commitElement.getElements();
        tblCommitContentList.setItems(elements);
        tblCommitContentList.getColumns().addAll(clnInclude, clnStatus, clnPath, clnModified);
        tabList.setContent(tblCommitContentList);
        tbpCommitContent.getTabs().add(tabList);

        Tab tabTree = new Tab("Tree");
        TreeView treContentTree = new TreeView();
        tabTree.setContent(treContentTree);
        tbpCommitContent.getTabs().add(tabTree);

        root.setCenter(tbpCommitContent);

        HBox commandBar = new HBox();
        commandBar.setPadding(new Insets(10, 10, 10, 10));
        commandBar.setAlignment(Pos.CENTER_RIGHT);

        Button btn = new Button();
        btn.setText("Commit");
        btn.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                Config.PROPERTIES.addMessageToHistory(txaMessage.getText());
                txaMessage.setText("");
                cbxHistoryMessage.getItems().clear();
                cbxHistoryMessage.getItems().addAll(Config.PROPERTIES.getHistoryMessageList());
            }
        });
        commandBar.getChildren().add(btn);

        root.setBottom(commandBar);

        primaryStage.setScene(new Scene(root, 800, 600));
        primaryStage.show();
    }

    class BooleanCell extends TableCell<CommitElement.Element, Boolean> {
        private CheckBox checkBox;

        public BooleanCell() {
            checkBox = new CheckBox();
            checkBox.setDisable(true);
            checkBox.selectedProperty().addListener(new ChangeListener<Boolean>() {
                public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
                    if(isEditing()) {
                        commitEdit(newValue == null ? false : newValue);
                    }
                }
            });
            this.setGraphic(checkBox);
            this.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
            this.setEditable(true);
        }

        @Override
        public void startEdit() {
            super.startEdit();
            if (isEmpty()) {
                return;
            }
            checkBox.setDisable(false);
            checkBox.requestFocus();
        }

        @Override
        public void cancelEdit() {
            super.cancelEdit();
            checkBox.setDisable(true);
        }

        public void commitEdit(Boolean value) {
            super.commitEdit(value);
            checkBox.setDisable(true);
        }

        @Override
        public void updateItem(Boolean item, boolean empty) {
            super.updateItem(item, empty);
            if (!isEmpty()) {
                checkBox.setSelected(item);
            }
        }
    }
}
